package masterjava.common.server.gwt.rpc.controller;

import masterjava.common.dao.DaoContextHolder;
import masterjava.common.dao.hibernate.FetchDaoContext;
import masterjava.common.dao.hibernate.TransactionHibernateDao;
import masterjava.common.shared.FetchContext;
import masterjava.common.shared.entity.GenericEntity;
import masterjava.common.shared.rpc.DaoRemoteService;

import java.io.Serializable;
import java.util.List;

/**
 * User: Grigory Kislin
 * Date: 27/06/11
 */
public class DaoRpcController extends GwtRpcController implements DaoRemoteService {

    private TransactionHibernateDao transactionHibernateDao;

    private DaoContextHolder daoContextHolder;

    public void setTransactionHibernateDao(TransactionHibernateDao transactionHibernateDao) {
        this.transactionHibernateDao = transactionHibernateDao;
    }

    public void setDaoContextHolder(DaoContextHolder daoContextHolder) {
        this.daoContextHolder = daoContextHolder;
    }

    @Override
    public GenericEntity get(String persistentClass, Serializable id) {
        return transactionHibernateDao.get(getEntityClass(persistentClass), id);
    }

    @Override
    public Serializable saveOrUpdate(GenericEntity entity) {
        return transactionHibernateDao.saveOrUpdate(entity);
    }

    @Override
    public List<? extends GenericEntity> loadAll(String persistentClass, FetchContext ctx) {
        setDaoContext(ctx);
        try {
            return transactionHibernateDao.loadAll(getEntityClass(persistentClass));
        } finally {
            daoContextHolder.setDaoContext(null);
        }
    }

    @Override
    public void delete(String persistentClass, Serializable id) {
        transactionHibernateDao.delete(getEntityClass(persistentClass), id);
    }

    @Override
    public List<? extends GenericEntity> findByNamedQueryAndNamedParam(String queryName, String[] paramNames, Serializable[] values, FetchContext ctx) {
        setDaoContext(ctx);
        try {
            return transactionHibernateDao.findByNamedQueryAndNamedParam(queryName, paramNames, values);
        } finally {
            daoContextHolder.setDaoContext(null);
        }
    }

    @Override
    public GenericEntity findUnique(String queryName, String[] paramNames, Serializable[] values) {
        return transactionHibernateDao.findUnique(queryName, paramNames, values);
    }

    private void setDaoContext(FetchContext ctx) {
        FetchDaoContext daoContext = new FetchDaoContext(ctx);
        daoContextHolder.setDaoContext(daoContext);
    }

    private Class<? extends GenericEntity> getEntityClass(String name) {
        try {
            return (Class<? extends GenericEntity>) Class.forName(name);
        } catch (ClassNotFoundException e) {
            throw logger.getIllegalStateException("Class " + name + " coudn't be instantiated", e);
        }
    }
}
